#include "precompiled.h"
#include "VolumeEnvelope.h"

using namespace AudioEngine;

VolumeEnvelope::VolumeEnvelope(sp<Producer> inner_producer, EnvelopeParameters const& parameters)
	: parameters(parameters)
{
	this->inner_producer = inner_producer;
	last_requested_rample = 0;
	first_sample_of_release = 0;
	release_mode = false;
}

static int msFromIndex(int index)
{
	return 1000 * (index / double(Producer::sample_rate));
}

/*override*/ float VolumeEnvelope::get_sample(int index) const
{
	last_requested_rample = index;
	float original = inner_producer->get_sample(index);
	int msPassed = msFromIndex(index);
	int msPassedAfterAttack = msPassed - parameters.get_attack();
	int msPassedOfRelease = msPassed - msFromIndex(first_sample_of_release);
	int msUntilSustain = parameters.get_decay() - msPassedAfterAttack;
	float sustained = parameters.get_sustain() * original;
	if(release_mode)
	{
		float coef = (1.0 - msPassedOfRelease / (double)parameters.get_release());
		if(coef > 0)
		{
			return original * coef * last_coef;
		}
		else
		{
			//sig_finished.invoke(); // this crashes due to lack of mutex. @TODO: reenable
			return 0;
		}
	}
	if(msPassedAfterAttack < 0)
	{
		last_coef = (msPassed / (double)parameters.get_attack());
		return original * last_coef;
	}
	else if(msPassedAfterAttack < parameters.get_decay())
	{
		float result = (original * msUntilSustain + sustained * msPassedAfterAttack) / parameters.get_decay();
		last_coef = result / original;
		return result;
	}
	else
	{
		return sustained;
	}
}

/*override*/ void VolumeEnvelope::key_release()
{
	first_sample_of_release = last_requested_rample;
	release_mode = true;
}
